import json
import re
import time
import traceback

from constants.global_variable import logger
from modules.email.email_fetcher import SafeEmailFetcher
from modules.email.email_info import EmailInfo
from utils import imap_util
from utils.http_utils import HttpUtils
from utils.time_utils import TimeUtils

email_fetcher = SafeEmailFetcher()

class EmailUtils:
    @staticmethod
    def get_email():
        email_str = email_fetcher.get_next_email()
        email_arr = email_str.split("----")
        email_type = EmailUtils.get_email_type(email_str)
        email_info: EmailInfo = EmailInfo(email_type=email_type)
        if len(email_arr) == 4: # microsoft
            for email_str in email_arr:
                if len(email_str) == 36:
                    email_info.set_client_id(email_str)
                elif len(email_str) > 400:
                    email_info.set_refresh_token(email_str)
                elif email_str.endswith('.com'):
                    email_info.set_email_address(email_str)
        else: # 非协议取码邮箱
            email_address = None
            for email_str in email_arr:
                if email_str.endswith('.com'):
                    email_address = email_str
                    email_info.set_email_address(email_address)
                elif email_type != 'netease' and email_info.request_url is None: # 126/163不需要取码地址
                    email_info.set_request_url(email_str)
            if email_type == 'netease':
                email_info.set_request_url('http://00mail.cn/prod-api/email/api/stand/getNewEmail?email=' + email_address)
        return email_info

    @staticmethod
    def get_email_type(email_str):
        if '@gmail.com' in email_str:
            return 'google'
        elif '@hotmail.com' in email_str or '@outlook.com' in email_str:
            return 'microsoft'
        elif '@163.com' in email_str or '@126.com' in email_str:
            return 'netease'
        elif '@icloud.com' in email_str:
            return 'icloud'
        else:
            return 'unknown'

    @staticmethod
    def get_register_email_code(email_info: EmailInfo, last_sms_code: str):
        email_info: EmailInfo = email_info
        max_attempts = 10  # 最大尝试次数
        attempt = 1
        while attempt <= max_attempts:
            # 获取验证码
            logger.info(f'即将第{attempt}次获取验证码')
            code = EmailUtils.request_sms_code(email_info)
            # 本次拿到6位验证码且与上次不相同
            if len(code) == 6 and code != last_sms_code:
                logger.info(f'获取验证码成功: {code}')
                return code
            attempt += 1
            time.sleep(5)
        logger.info(f'获取验证码失败')
        return ''

    @staticmethod
    def request_sms_code(email_info: EmailInfo):
        try:
            if email_info.email_type == 'google':
                result = json.loads(HttpUtils.send_get_text(email_info.request_url))
                if result['code'] == 200:
                    # 只取3分钟内的邮件
                    data = result['data']
                    if not TimeUtils.is_over_3_minutes(data['receiveTimestamp']):
                        # 优先从code中取
                        if data['code']:
                            if len(data['code']) == 6:
                                return data['code']
                        else:
                            # 没返回code时从邮件内容中取
                            match = re.search(r'\d{6}', data['title'])
                            if match:
                                return match.group()
            elif email_info.email_type == 'microsoft':
                code = imap_util.request_ins_email_code(email_info.email_address, email_info.client_id,
                                                        email_info.refresh_token)
                if len(code) == 6:
                    return code
            elif email_info.email_type == 'netease':
                result = json.loads(HttpUtils.send_get_text(email_info.request_url))
                if result['code'] == 200:
                    # 只取3分钟内的邮件
                    data = result['data']
                    timestamp = TimeUtils.to_utc_ms(data['sentDate'])
                    if not TimeUtils.is_over_3_minutes(timestamp):
                        match = re.search(r'\d{6}', data['subject'])
                        if match:
                            return match.group()
            elif email_info.email_type == 'icloud':
                result = json.loads(HttpUtils.send_get_text(email_info.request_url))
                if 'code' in result and result['code'] == 1:
                    data = result['data']
                    match = re.search(r'\d{6}', data['email_code'])
                    if match:
                        return match.group()
        except Exception as e:
            logger.error(f'本次获取验证码出错: {e}')
            stack_trace = traceback.format_exc()
            logger.error(stack_trace)
        return ''
